<?php


namespace app\common\services;

use app\common\libs\InsideApi;
use app\common\loader\ModelMerchant;
use Firebase\JWT\JWT;
use yiqiniu\extend\db\YqnModel;
use yiqiniu\extend\exception\ApiException;

/**
 * 公共的基础类
 * Class HelperService
 * @package app\common\services
 */
class HelperService
{
    /**
     * @var array
     */

    //处理方式，cache:true 缓存全表300秒，cache:false  不缓存按条件查询,
    //field  以,分隔,  每1个为key 第2个为值,多个字段用|分隔
    //

    private array $_dict = [
        // 格式: 'xxx'=>['table'=>'xxx','field'=>'id,title|mobile','cache'=>false]
        // 例:  'dept' => [ 'table' => 'admin_dept', 'field' => 'id,title', 'cache' => false]
        // 例2:  'dept' => [ 'table' => 'admin_dept', 'field' => 'id,title|mobile', 'cache' => false]
        'product' => ['table' => 'product', 'field' => 'id,title', 'cache' => false],
        'product_class' => ['table' => 'product_class', 'field' => 'id,title', 'cache' => false],
        'merchant' => ['table' => 'merchant', 'field' => 'id,username', 'cache' => false],
        'merchant_info' => ['table' => 'merchant_info', 'field' => 'mer_id,title', 'cache' => true],
        'role' => ['table' => 'merchant_roles', 'field' => 'id,title', 'cache' => true],
        'dept' => ['table' => 'merchant_department', 'field' => 'id,title', 'cache' => true],
        'system_dept' => ['table' => 'system_department', 'field' => 'id,title', 'cache' => true],
        'shop' => ['table' => 'shop', 'field' => 'id,title', 'cache' => false],
        'promo' => ['table' => 'virtual_promo', 'field' => 'id,title', 'cache' => true],
        'salesman' => ['table' => 'shop_salesman', 'field' => 'id,name', 'cache' => true],
        'merchant_system_api' => ['table' => 'merchant_system_api', 'field' => 'id,title', 'cache' => false],
        'system_api' => ['table' => 'system_api', 'field' => 'id,title', 'cache' => false],
        'system_manager' => ['table' => 'system_manager', 'field' => 'id,username', 'cache' => true],
    ];

    /**
     * 显示详情中字段的标题
     * @param mixed $info 要处理的数据
     * @param array $dictS 从表中读取的字典数据
     * @param array $configDict 从配置文件中读取查询数据
     */
    public function showInfoTitle(&$info, array $dictS = [], array $configDict = []): void
    {
        if (empty($info)) {
            return;
        }

        $list = [$info];
        $this->showListTitle($list, $dictS, $configDict);
        $info = current($list);
    }

    /**
     * 根据列表，指定类型的ID，显示出指定的名称, 会将_id, 替换为_tag
     * @param array $dataList 要处理的数据
     * @param array $dictS 从表中读取的查询数据
     * @param array $configDict 从配置文件中读取查询数据
     * @example
     *  Services::Helper()->showListTitle(
     *          $pageList['data'],                                                   // 要处理的数据
     *          ['role' => 'group_id', 'dept' => 'dept_id'],                         // 从数据库读取
     *          ['status' => 'system.status', 'flag' => ['1'=>'大','2'=>'小']]        // 值为字符串,从配置中读取,数组:直接使用
     *    );
     */
    public function showListTitle(array &$dataList, array $dictS = [], array $configDict = []): void
    {
        if (empty($dataList) || (empty($dictS) && empty($configDict)) || !is_array(current($dataList))) {
            return;
        }
        $valid_dict = [];
        if (!empty($dictS)) {
            // 移除无效的字典类
            $valid_dict = array_intersect(array_keys($dictS), array_keys($this->_dict));
            if (empty($valid_dict)) {
                return;
            }
            // 取出有效的字典字段
            $dict_field = explode(',', implode(',', array_values($dictS)));
            // 取出有效字段
            $valid_field = array_intersect(array_keys(current($dataList)), $dict_field);
            if (empty($valid_field)) {
                return;
            }

            foreach ($dictS as $k => $v) {
                foreach ($valid_field as $k2 => $str) {
                    if (strpos($v, $str) !== false) {
                        $valid_dict[$k] = $v;
                        unset($valid_field[$k2]);
                        break;
                    }
                }
            }
            unset($valid_field, $dict_field);
        }
        // 加入配置的获取
        foreach ($configDict as $config => $val) {
            $valid_dict[$config] = $val;
        }
        // $show_field 需要处理的字段
        // $result_dict 结果的字段数据
        $result_dict = $show_field = [];

        foreach ($valid_dict as $key => $dict) {
            // 判断是否数据表
            if (isset($this->_dict[$key]) && !empty($this->_dict[$key]['table'])) {
                $obj = (new YqnModel())->name($this->_dict[$key]['table']);
                if ($obj === null) {
                    continue;
                }
                // 生成要查询的字段
                if (is_array($this->_dict[$key]['field'])) {
                    $pkid = $this->_dict[$key]['key'];
                    $field = $this->_dict[$key]['field'];
                } else {
                    [$pkid, $field] = explode(',', $this->_dict[$key]['field']);
                }


                $showField = $field;
                // 处理多个字段
                if (strpos($field, '|') !== false) {
                    $field = 'concat(' . str_replace('|', ",'|',", $field) . ') as field';
                    $showField = 'field';
                }
                // 显示标题
                $show_key = explode(',', $dict);

                $cache_flag = $this->_dict[$key]['cache'] ?? false;
                //处理方式，缓存的不需要条件，不缓存的需要按条件查询
                if ($cache_flag) {
                    // 从数据库中获取对并对应的字典列表
                    $title_list = $obj->removeOption()
                        ->cache($this->_dict[$key]['table'] . '_list_title_cache', YqnModel::DEFAULT_CACHE_TIME, $this->_dict[$key]['table'])
                        ->field([$field, $pkid])->select();

                } else {
                    // 生成要查询的条件； 使用wherein 来进查询，生成in 的内容项。
                    $search_ids = [];
                    foreach ($show_key as $id_field) {
                        if (isset(current($dataList)[$id_field])) {
                            $search_ids = array_unique(array_merge($search_ids, array_column($dataList, $id_field)));
                        }
                    }
                    // 从数据库中获取对并对应的字典列表
                    //将查询结果转抱key,value格式
                    $title_list = $obj->removeOption()->where($pkid, 'in', $search_ids)->field([$field, $pkid])->select();
                }
                $title_list = array_column($title_list, $showField, 'id');
            } else {
                if (is_array($dict)) {
                    $title_list = $dict;
                } else {
                    $title_list = config($dict);
                }
                // 显示标题
                $show_key = explode('|', $key);
            }

            foreach ($show_key as $k) {
                $show_field[$k] = $key;
            }
            $result_dict[$key] = $title_list;
        }
        foreach ($dataList as &$row) {
            foreach ($show_field as $field => $dict) {
                if (isset($row[$field])) {
                    $row[str_replace('_id', '', $field) . '_tag'] = $result_dict[$dict][$row[$field]] ?? '';
                }
            }
        }
    }

    /**
     * @param string $key secret key
     * @param int $expire 过期时间
     * @param array $data 加密的数据
     * @return array
     * @throws ApiException
     */
    public function getToken(string $key, int $expire, array $data)
    {
        try {
            if (empty($key)) {
                api_exception(400, 'no set token key');
            }
            $time = time(); //当前时间

            //公用信息
            $token = [
                'iss' => request()->Domain(), //签发者 可选
                'iat' => $time, //签发时间
                'data' => $data
            ];

            $access_token = $token;
            $access_token['scopes'] = 'role_access'; //token标识，请求接口的token
            if ($expire > 0) {
                $access_token['exp'] = $time + $expire; //access_token过期时间,这里设置6个小时
                $refresh_token['exp'] = $time + REFRESH_TOKEN_TIMEOUT; //access_token过期时间,这里设置30天
            }


            $refresh_token = $token;
            $refresh_token['scopes'] = 'role_refresh'; //token标识，刷新access_token


            return [
                'access_token' => JWT::encode($access_token, $key),
                'refresh_token' => JWT::encode($refresh_token, $key),
            ];

        } catch (ApiException $e) {
            throw  $e;
        } catch (\Exception $e) {
            throw  $e;
        }
    }

    /**
     * 获取微信的信息
     * @param string $openid
     * @return array
     * @throws \Exception
     */
    public function getWechatUserInfo(string $openid): array
    {
        $result = ['nick_name' => '未知', 'head_img' => '', 'bind' => 0, 'union_id' => ''];
        if (!empty($openid)) {

            $config = config('wechat');
            $res = InsideApi::Wechat()->Oauth()->GetWxInfo(['openid' => $openid, 'client_id' => $config['app_id'] ?? '']);
            if (empty($res) || $res['code'] != 200) {
                api_exception(400, $res['msg'] ?? '');
            }
            if (!empty($res['data'])) {
                $wxdata = &$res['data'];
                $result['nick_name'] = $wxdata['nickname'];
                $result['head_img'] = $wxdata['headimgurl'];
                $result['bind'] = 1;
                $result['union_id'] = $wxdata['union_id'] ?? '';
            }
        }
        return $result;
    }

    /**
     * 根据商品code显示商品名称
     * @param string $merId 商品ID
     * @param array $dataList 处理列表
     * @param string $field 处理的字段
     * @return void
     */
    public function showProductCodeTitle(string $merId, array &$dataList, string $field = 'product_code')
    {
        if (!empty($dataList)) {
            $product_code = array_unique(array_column($dataList, $field));
            $product_list = ModelMerchant::Product()->where('mer_id', $merId)
                ->whereIn('code', $product_code)
                ->column(null, 'title', 'code');

            foreach ($dataList as &$row) {
                if (isset($row[$field])) {
                    $row['product_tag'] = $product_list[$row[$field]] ?? '';
                }
            }

        }

    }

    /**
     * 显示详情中商品Code名称
     * @param string $merId
     * @param array $dataInfo
     * @param string $field
     * @return void
     */
    public function showInfoProductCodeTitle(string $merId, array &$dataInfo, string $field = 'product_code')
    {
        if (!empty($dataList)) {
            $product_title = ModelMerchant::Product()->where('mer_id', $merId)
                ->where('code', $dataInfo[$field])->value(null, 'title,subtitle');
            $dataInfo['product_tag'] = $product_title ?? '';
        }

    }
}
